/**
  ******************************************************************************
  * @file      timer.c
  * @author    Dragon.Chen
  * @version   V1.0.2
  * @date      12-10-2014
  * @brief     定时器容器(时间粒度为秒，也意味最大误差为1秒，如果需要高精度，使用gettimeofday)
  * @attention 由于定时器用于心跳包，回调函数都是一样，出于对内存和效率考虑，直接将回调函数放在
  *            Timer_Manage_T的结构体，统一管理。如果有特殊需求，请分别对每个定时器设置回调函数。
  ******************************************************************************
  *
  * <h2><center>&copy; COPYRIGHT 2014 上海今中网络科技有限公司 </center></h2>
  ******************************************************************************
  */

#include "timer.h"

TIMER_MANAGE_T  timerManage;

/**
  * @brief  初始化定时器
  * @param  arg1:最大容量  arg2:回调函数
  * @retval NULL
  */
void init_timer(int max, TIMER_EVENT_T *cb)
{
    timerManage.timerSize  = 0;
    timerManage.timerMax   = max;
    timerManage.timerArray = (TIMER_T **)calloc(timerManage.timerMax, sizeof(TIMER_T *));
    timerManage.callback   = cb;
}

/**
  * @brief  添加定时器(完全二叉树的左儿子是2i+1,右儿子是2i+2,父节点是(i-1)/2 (i>0))
  *         添加原理:
  *              21                    21               21                 14
  *             /  \                  /  \             /  \               /  \
  *           24    31   插入14=>    24    31   =>    24    []   =>      24    21
  *          /  \   /              /  \   / \       /  \   / \         /  \   / \
  *         65  26 32             65  26 32 []     65  26 32 31       65  26 32 31
  * @param  arg1:定时器
  * @retval 成功返回0，否则-1
  */
int add_timer(TIMER_T *timer)
{
    int hole, parent;

//    if (timer == NULL || timerManage.timerSize == WORKER_MAX_NCLIENT)
//        return -1;

    for (hole = timerManage.timerSize++; hole>0; hole=parent)
    {
        parent = (hole-1) / 2;
        if (timer->expire >= timerManage.timerArray[parent]->expire)
            break;

        timerManage.timerArray[hole] = timerManage.timerArray[parent];
        timerManage.timerArray[hole]->index = hole;
    }

    timerManage.timerArray[hole] = timer;
    timerManage.timerArray[hole]->index = hole;
    return 0;
}

/**
  * @brief  删除定时器
  * @param  arg1:定时器
  * @retval NULL
  */
void delete_timer(TIMER_T *timer)
{
    if (timer == NULL || timerManage.timerSize == 0)
        return;

    if (timer->index == (timerManage.timerSize-1))
    {
        timerManage.timerArray[--timerManage.timerSize] = NULL;
        return;
    }

    timerManage.timerArray[timer->index] = timerManage.timerArray[--timerManage.timerSize];
    timerManage.timerArray[timerManage.timerSize] = NULL;
    percolate_down(timer->index);
}

/**
  * @brief  定时器检测事件
  * @param  arg1:void
  * @retval NULL
  *
  */
void timer_tick()
{
    time_t   currentTime = time(NULL);
    TIMER_T *tempTimer   = timerManage.timerArray[0];

    while (1)
    {
        if (tempTimer == NULL)
            break;

        if (tempTimer->expire > currentTime)
            break;

        /* added statement starts here */
        if (tempTimer->clientData->nLostHeartBeat > 0 && tempTimer->clientData->nLostHeartBeat < 2)
        {
            tempTimer->clientData->nLostHeartBeat++;
            adjust_timer(tempTimer, currentTime + WORKER_HEARTBEAT_TIMEOUT);
            tempTimer = timerManage.timerArray[0];
            continue;
        }
        /* ends here */

        timerManage.callback(tempTimer->clientData, EVENT_OF_TIMER);

        if (timerManage.timerSize <= 1)
        {
            timerManage.timerSize = 0;
            timerManage.timerArray[0] = NULL;
            break;
        }
        else
        {
            timerManage.timerArray[0] = timerManage.timerArray[--timerManage.timerSize];
            timerManage.timerArray[timerManage.timerSize] = NULL;
            percolate_down(0);
            tempTimer = timerManage.timerArray[0];
        }
    }
}

/**
  * @brief  释放所有的定时器
  * @param  arg1:void
  * @retval NULL
  */
void finalize_timer()
{
    if (timerManage.timerArray)
    {
        free(timerManage.timerArray);
        timerManage.timerArray = NULL;
    }
}

/******************* (C) COPYRIGHT 2014 上海今中网络科技有限公司 *****END OF FILE****/


